//
// Created by tang on 23-3-12.
//

#ifndef PIINFO_CFG_SERVICE_HPP
#define PIINFO_CFG_SERVICE_HPP

#include <memory>
#include <concepts>
#include <type_traits>
#include "metadata/variant.h"
#include "service/svc_manager.hpp"
#include "utils/safe_value.hpp"

class PI_API IConfigService: public TaggedService<service_type::config>
{
public:
    class IGroup {
    public:
        virtual ~IGroup() = default;

        template <typename T, typename V> requires std::is_constructible_v<T,V>
        PI_INLINE IGroup *input(const std::string &key, const std::string &caption, safe_value<T>* &v, V def = {}, const std::string &help = {})
        {
            T def_t{def};
            return input_impl (key, caption, &v, (value_type)value_traits<T>::store_type, &def_t, help);
        }

        template <typename T, typename V> requires std::is_constructible_v<T,V>
        PI_INLINE IGroup *secret(const std::string &key, const std::string &caption, safe_value<T>* &v, V def = {}, const std::string &help = {})
        {
            T def_t{def};
            return secret_impl (key, caption, &v, (value_type)value_traits<T>::store_type, &def_t, help);
        }

        template <typename T, typename V> requires std::is_constructible_v<T,V>
        PI_INLINE IGroup *slider(const std::string &key, const std::string &caption, safe_value<T>* &v, T min, T max, V def = {}, const std::string &help = {})
        {
            T def_t{def};
            return slider_impl (key, caption, &v, (value_type)value_traits<T>::store_type, (void*)(long)min, (void*)(long)max, help);
        }

        PI_INLINE IGroup *checkbox(const std::string &key, const std::string &caption, safe_value<bool>* &v, bool def = false, const std::string &help = {})
        {
            return checkbox_impl (key, caption, &v, &def, help);
        }

        PI_INLINE IGroup *toggle(const std::string &key, const std::string &caption, safe_value<bool>* &v, bool def = false, const std::string &help = {})
        {
            return toggle_impl (key, caption, &v, &def, help);
        }

        template <typename T, typename V> requires requires { std::is_integral_v<T> && std::is_constructible_v<T,V>; }
        PI_INLINE IGroup *select(const std::string &key, const std::string &caption, safe_value<T>* &v, const char*(*text)(void *user, int idx), int count, void *user, V def = {}, const std::string &help = {})
        {
            T def_t{def};
            return select_impl (key, caption, &v, (value_type)value_traits<T>::store_type, text, count, user, &def_t, help);
        }

        template <typename T, typename V> requires requires { { (value_type)value_traits<T>::store_type } -> std::same_as<value_type>; }
        PI_INLINE IGroup *data(const std::string &key, T* &v, V def = {}) {
            T def_t{def};
            return data_impl (key, &v, (value_type)value_traits<T>::store_type, &def_t);
        }

        virtual std::unique_ptr<IGroup> child_group(const char *key, const std::string &display) = 0;

    protected:
        virtual PI_API IGroup *input_impl(const std::string &key, const std::string &caption, void *value_holder, value_type vt, void *def, const std::string &help) = 0;
        virtual PI_API IGroup *secret_impl(const std::string &key, const std::string &caption, void *value_holder, value_type vt, void *def, const std::string &help) = 0;
        virtual PI_API IGroup *slider_impl(const std::string &key, const std::string &caption, void *value_holder, value_type vt, void *min, void *max, void *def, const std::string &help) = 0;
        virtual PI_API IGroup *checkbox_impl(const std::string &key, const std::string &caption, void *value_holder, void *def, const std::string &help) = 0;
        virtual PI_API IGroup *toggle_impl(const std::string &key, const std::string &caption, void *value_holder, void *def, const std::string &help) = 0;
        virtual PI_API IGroup *select_impl(const std::string &key, const std::string &caption, void *value_holder, value_type vt, const char*(*text)(void *user, int idx), int count, void *user, void *def, const std::string &help) = 0;
        virtual PI_API IGroup *data_impl(const std::string &key, void *value_holder, value_type vt, void *def) = 0;
    };

    virtual std::unique_ptr<IGroup> group(const char *key, const std::string &display) = 0;
};

#endif  // PIINFO_CFG_SERVICE_HPP
